import { h, computed } from 'vue';
import { MessageArgsProps } from 'ant-design-vue';
import printJS from 'print-js';
import { useI18n } from '@/hooks/web/useI18n';
import { useAuth } from '@/hooks/web/useAuth';
import { useMessage } from '@/hooks/web/useMessage';
import { withInstall } from '@/utils';
import { isFunction } from '@/utils/is';
import type { ContextMenuItem } from '@/components/ContextMenu';
import { useModal } from '@/components/AdVxeModal';
import { useLoading } from '@/components/Loading';
import { PrintProps } from './src/props';
import { ErrorMessageMode } from './src/typing';
import printTemplateModal from './src/PrintTemplateModal.vue';

import {
  PrintReportArgumentDto,
  PrintReportRequestDto,
  PrintReportOutputDto,
} from '@/api/report/model/print';
import {
  getPrintTemplatesByCode,
  cancelDefaultPrints,
  setDefaultPrints,
  getPrintReportFile,
  getPrintReportBase64,
} from '@/api/report/print';
import {
  PrintTemplateUserOutputDto,
  PrintUserDtoSimple,
  PrintTemplateUserDtoSimple,
} from '@/api/report/admin/print/model';

// import { downloadByBase64 } from '@/utils/file/download';

/** 打印模板模态窗 */
export const PrintTemplateModal = withInstall(printTemplateModal);

/**
 * 使用高级打印
 * @param props 打印参数
 * @returns 打印功能对象集
 */
export function useAdPrint(props: PrintProps) {
  const { formIndex, keyField, getFormData } = props;
  const { t } = useI18n();
  const [modalRegister, modalMethods] = useModal();
  const { createMessage, createErrorModal } = useMessage();
  const error = createMessage.error!;

  // 打印处理Loading
  const [openPrintLoading, closePrintLoading] = useLoading({
    tip: t('component.print.printProcessingTip'),
  });

  // 启用授权：默认启用
  const enableAuth = props?.enableAuth === undefined ? true : props.enableAuth;
  const permission = {
    print: props?.permission?.print || [
      'Root.Report.Rpt.GetPrintReportFile',
      'Root.Report.Rpt.GetPrintReportBase64',
    ],
    preview: props?.permission?.preview || 'Root.Report.Rpt.Preview',
    template: props?.permission?.template || [
      'Root.Report.Rpt.GetPrintReportFile',
      'Root.Report.Rpt.GetPrintReportBase64',
    ],
  };

  //#region 获取模板集合
  /**
   * 获取模板集合
   * @param printCode 打印编码
   * @returns 打印模板用户输出DTO集合
   */
  async function getTemplates(printCode?: string): Promise<PrintTemplateUserOutputDto[]> {
    const result = await getPrintTemplatesByCode(printCode || formIndex);
    if (result?.Type === 200) {
      return result.Data as PrintTemplateUserOutputDto[];
    }
    return [];
  }
  //#endregion
  //#region 设置默认打印模板
  /**
   * 设置默认打印模板
   * @param dtos 打印模板用户简单DTO集合
   */
  async function setDefaultTemplate(dtos: PrintTemplateUserDtoSimple[]): Promise<boolean> {
    const setDefaultHandler = props.handler?.printTemplateSetDefaultHandler;
    if (setDefaultHandler && isFunction(setDefaultHandler)) {
      return await setDefaultHandler(getArguments());
    } else {
      const result = await setDefaultPrints(dtos);
      return result?.Type === 200;
    }
  }
  //#endregion
  //#region 取消默认打印模板
  /**
   * 取消默认打印模板
   * @param dtos 打印用户简单DTO集合
   */
  async function cancelDefaultTemplate(dtos: PrintUserDtoSimple[]): Promise<boolean> {
    const setDefaultHandler = props.handler?.printTemplateSetDefaultHandler;
    if (setDefaultHandler && isFunction(setDefaultHandler)) {
      return await setDefaultHandler(getArguments());
    } else {
      const result = await cancelDefaultPrints(dtos);
      return result?.Type === 200;
    }
  }
  //#endregion

  //#region 获取参数集合
  /**
   * 获取参数集合
   * @returns 报表参数DTO集合
   */
  function getArguments(): PrintReportArgumentDto[] {
    const parameterDtos: PrintReportArgumentDto[] = [];
    const formValues = getFormData();
    if (formValues) {
      for (const key in formValues) {
        // console.log(key, formValues[key]);
        parameterDtos.push({ Key: key, Value: formValues[key] });
      }
    }
    return parameterDtos;
  }
  //#endregion

  //#region 获取打印报告
  /**
   * 获取打印报告
   * @param dto 报表查询请求DTO
   * @param base64 是否Base64编码，默认是
   * @param errorMessageMode 错误消息模型
   * @returns base64：true-报告文件对象、false-报表输出DTO对象
   */
  async function getPrintReport(
    dto: PrintReportRequestDto,
    base64 = true,
    errorMessageMode: ErrorMessageMode = 'message',
  ): Promise<any> {
    if (!dto) {
      return null;
    }
    // 处理参数逻辑
    if (!dto.Arguments) {
      dto.Arguments = getArguments();
    }
    if (!dto.Key) {
      dto.Key = keyField;
    }
    if (!dto.Value) {
      dto.Value = dto.Arguments.find((o) => {
        return o.Key === keyField;
      })?.Value.toString();
    }
    // 请求接口
    if (base64 === true) {
      const result = await getPrintReportBase64(dto, errorMessageMode);
      if (result?.Type === 200) {
        return result.Data as PrintReportOutputDto;
      }
      return null;
    } else {
      const result = await getPrintReportFile(dto, errorMessageMode);
      return result;
    }
  }
  //#endregion

  //#region 根据打印编码获取打印报告
  /**
   * 根据打印编码获取打印报告
   * @param printCode 打印编码
   * @param requestFormat 请求的格式（html、image、pdf、csv、excel、word、ppt）
   * @param showTemplateModal 当存在多个模板且无默认时是否弹选择窗口
   * @param base64 是否Base64编码，默认是
   * @param errorMessageMode 错误消息模型
   * @returns base64：true-报告文件对象、false-报表输出DTO对象
   */
  async function getPrintReportByPrintCode(
    printCode?: string,
    requestFormat: 'html' | 'image' | 'pdf' | 'csv' | 'excel' | 'word' | 'ppt' = 'pdf',
    showTemplateModal = true,
    base64 = true,
    errorMessageMode: ErrorMessageMode = 'message',
  ): Promise<any> {
    if (!printCode) {
      printCode = formIndex;
    }
    // 打印模板处理逻辑
    const templateDtos = await getTemplates(printCode);
    if (!templateDtos || templateDtos?.length <= 0) {
      const errMessage = t('component.print.printTemplateUnavailableTip');
      if (errorMessageMode === 'modal') {
        createErrorModal({
          zIndex: 999999999,
          title: () => h('span', t('sys.api.errorTip')),
          content: () => h('span', errMessage),
        });
      } else if (errorMessageMode === 'message') {
        const messageProps: MessageArgsProps = {
          content: errMessage,
          duration: undefined,
          type: 'error',
          key: `global_error_message_print_template_unavailable`,
        };
        error(messageProps);
      }
      return null;
    }
    let templateDto: PrintTemplateUserOutputDto | null | undefined = null;
    if (templateDtos.length === 1) {
      templateDto = templateDtos[0];
    } else {
      templateDto = templateDtos.find((item) => item.IsDefault === true);
    }
    if (!templateDto && showTemplateModal) {
      //TODO:当存在多个模板且没有默认模板时，弹出模板窗体以供手动选择
      openTemplateModal();
      return null;
    }
    // 打印报告处理逻辑
    const queryArguments = getArguments();
    const requestDto: PrintReportRequestDto = {
      TemplateId: templateDto?.TemplateId,
      Key: keyField,
      Value: queryArguments
        .find((o) => {
          return o.Key === keyField;
        })
        ?.Value.toString(),
      Arguments: queryArguments,
      RequestFormat: requestFormat,
    };
    const result = await getPrintReport(requestDto, base64);
    return result;
  }
  //#endregion

  //#region 执行打印
  /**
   * 执行打印
   * @param templateId 模板编号
   * @param errorMessageMode 错误消息模型
   */
  async function executePrint(
    templateId: string | bigint,
    errorMessageMode: ErrorMessageMode = 'message',
  ): Promise<void> {
    try {
      openPrintLoading();
      // 打印报告处理逻辑
      const queryArguments = getArguments();
      const requestDto: PrintReportRequestDto = {
        TemplateId: templateId,
        Key: keyField,
        Value: queryArguments
          .find((o) => {
            return o.Key === keyField;
          })
          ?.Value.toString(),
        Arguments: queryArguments,
        RequestFormat: 'pdf',
      };
      // console.log(requestDto);
      // const result2 = await getPrintReport(
      //   {
      //     TemplateId: templateId,
      //     Key: keyField,
      //     Value: queryArguments
      //       .find((o) => {
      //         return o.Key === keyField;
      //       })
      //       ?.Value.toString(),
      //     Arguments: queryArguments,
      //     RequestFormat: 'ppt',
      //   },
      //   true,
      //   errorMessageMode,
      // );
      // console.log('aa', result2);
      // downloadByBase64(`${result2.Base64Header}${result2.Data}`, 'aaa.pptx');

      const result = await getPrintReport(requestDto, true, errorMessageMode);
      if (result) {
        const outputDto = result as PrintReportOutputDto;
        if (outputDto.Data) {
          executePrintInner(outputDto.Data, 'pdf', true);
        }
      }
    } finally {
      closePrintLoading();
    }
  }
  //#endregion
  //#region 执行打印-内部
  /**
   * 执行打印-内部
   * @param printable 打印的内容
   * @param printType 打印类型，默认 pdf
   * @param base64 是否Base64格式，默认 true
   * @param showModal 启用此选项可在检索或处理大型PDF文件时显示用户反馈
   * @param modalMessage 反馈的消息内容
   */
  function executePrintInner(
    printable: any,
    printType: 'json' | 'html' | 'pdf' | 'image' | 'raw-html' = 'pdf',
    base64 = true,
    showModal = false,
    modalMessage: string = t('component.print.printProcessingTip'),
  ) {
    if (printable) {
      printJS({
        printable: printable,
        type: printType,
        showModal: showModal, // 启用此选项可在检索或处理大型PDF文件时显示用户反馈。
        modalMessage: modalMessage || t('component.print.printProcessingTip'),
        base64: base64,
      });
    }
  }
  //#endregion

  //#region 创建模板模态窗体
  /** 打开模板模态窗体
   * @param printCode 打印编码
   */
  function openTemplateModal(printCode?: string) {
    modalMethods.openModal(true, { printCode });
  }
  //#endregion

  //#region 打印上下文菜单集合
  const contextMenus: ContextMenuItem[] = [];

  if (formIndex) {
    const { hasAuth } = useAuth();
    const printContextMenu = !enableAuth || (enableAuth && hasAuth(permission.print));
    const printPreviewContextMenu = !enableAuth || (enableAuth && hasAuth(permission.preview));
    const printTemplateContextMenu = !enableAuth || (enableAuth && hasAuth(permission.template));
    if (printContextMenu) {
      contextMenus.push({
        label: t('component.print.printText'),
        icon: 'bytesize:print',
        handler: async () => {
          if (props.handler?.printHandler && isFunction(props.handler?.printHandler)) {
            await props.handler.printHandler(getArguments());
          } else {
            try {
              openPrintLoading();
              const result = await getPrintReportByPrintCode(formIndex, 'pdf', true, true);
              if (result) {
                const outputDto = result as PrintReportOutputDto;
                if (outputDto.Data) {
                  executePrintInner(outputDto.Data, 'pdf', true);
                }
              }
            } finally {
              closePrintLoading();
            }
          }
        },
      });
    }
    if (printPreviewContextMenu) {
      contextMenus.push({
        label: t('component.print.printPreview'),
        icon: 'uiw:printer',
        handler: async () => {
          if (
            props.handler?.printPreviewHandler &&
            isFunction(props.handler?.printPreviewHandler)
          ) {
            await props.handler.printPreviewHandler(getArguments());
          } else {
            try {
              openPrintLoading();
              const result = await getPrintReportByPrintCode(formIndex, 'pdf', true, true);
              if (result) {
                const outputDto = result as PrintReportOutputDto;
                if (outputDto.Data) {
                  executePrintInner(outputDto.Data);
                }
              }
            } finally {
              closePrintLoading();
            }
          }
        },
      });
    }
    if (printTemplateContextMenu) {
      contextMenus.push({
        label: t('component.print.printTemplate'),
        icon: 'carbon:data-format',
        handler: async () => {
          if (
            props.handler?.printTemplateHandler &&
            isFunction(props.handler?.printTemplateHandler)
          ) {
            await props.handler.printTemplateHandler({ formIndex });
          } else {
            //TODO:处理打印模板逻辑
            openTemplateModal();
          }
        },
      });
    }
  }
  //#endregion

  // 方法组
  const methods = {
    /**
     * 获取模板集合
     * @param printCode 打印编码
     * @returns 打印模板用户输出DTO集合
     */
    getTemplates: async (printCode?: string) => {
      return await getTemplates(printCode);
    },
    /**
     * 设置默认打印模板
     * @param dtos 打印模板用户简单DTO集合
     */
    setDefaultTemplate: async (dtos: PrintTemplateUserDtoSimple[]) => {
      return await setDefaultTemplate(dtos);
    },
    /**
     * 取消默认打印模板
     * @param dtos 打印用户简单DTO集合
     */
    cancelDefaultTemplate: async (dtos: PrintUserDtoSimple[]) => {
      return await cancelDefaultTemplate(dtos);
    },
    /**
     * 获取参数集合
     * @returns 报表参数DTO集合
     */
    getArguments: () => {
      return getArguments();
    },
    /**
     * 获取打印报告
     * @param dto 报表查询请求DTO
     * @param base64 是否Base64编码，默认是
     * @param errorMessageMode 错误消息模型
     * @returns base64：true-报告文件对象、false-报表输出DTO对象
     */
    getReport: async (
      dto: PrintReportRequestDto,
      base64 = true,
      errorMessageMode: ErrorMessageMode = 'message',
    ) => {
      return await getPrintReport(dto, base64, errorMessageMode);
    },
    /**
     * 根据打印编码获取打印报告
     * @param printCode 打印编码
     * @param requestFormat 请求的格式（html、image、pdf、csv、excel、word、ppt）
     * @param showTemplateModal 当存在多个模板且无默认时是否弹选择窗口
     * @param base64 是否Base64编码，默认是
     * @param errorMessageMode 错误消息模型
     * @returns base64：true-报告文件对象、false-报表输出DTO对象
     */
    getReportByCode: async (
      printCode?: string,
      requestFormat: 'html' | 'image' | 'pdf' | 'csv' | 'excel' | 'word' | 'ppt' = 'pdf',
      showTemplateModal = true,
      base64 = true,
      errorMessageMode: ErrorMessageMode = 'message',
    ) => {
      return await getPrintReportByPrintCode(
        printCode,
        requestFormat,
        showTemplateModal,
        base64,
        errorMessageMode,
      );
    },
    /**
     * 执行打印
     * @param templateId 模板编号
     * @param errorMessageMode 错误消息模型
     */
    executePrint: async (
      templateId: string | bigint,
      errorMessageMode: ErrorMessageMode = 'message',
    ) => {
      return await executePrint(templateId, errorMessageMode);
    },
    /** 打开模板模态窗体
     * @param printCode 打印编码
     */
    openTemplateModal: async (printCode?: string) => {
      openTemplateModal(printCode);
    },
  };

  // 模板模态窗体参数
  const templateModalProps = computed(() => {
    return {
      printCode: formIndex,
      getTemplatesApi: getTemplates,
      setDefaultTemplateApi: setDefaultTemplate,
      cancelDefaultTemplateApi: cancelDefaultTemplate,
      executePrintApi: executePrint,
    };
  });

  return {
    printContextMenus: contextMenus,
    templateModalRegister: modalRegister,
    templateModalMethods: modalMethods,
    templateModalProps,
    ...methods,
  };
}
